import json
import datetime
import traceback
from models import Chat, Kumquats, Orders, Users
from common.log import logger
from pydantic_models import WXWorkIn
from sqlalchemy.orm import Session


class ChatHandler:
    def __init__(self, wxmsg: WXWorkIn, db: Session = None):
        """
        初始化ChatHandler
        
        Args:
            wxmsg: 企业微信消息对象
            db: 数据库会话（可选，如果不提供则使用传统方式创建）
        """
        self.wxmsg = wxmsg
        self.db = db  # 存储数据库会话
        self.user_id = None
        self.user = None  # 用户对象
        self.name = None  # 用户姓名
        self.nickname = None  # 用户昵称
        self.role = None  # 用户角色
        self.query = ""
        self.answer = ""
        self.ai_answer = ""
        self.actions = []
        self.note = ""
        
        # 如果没有提供数据库会话，使用传统方式（向后兼容）
        if self.db is None:
            logger.warning("[聊天处理器] ⚠️ 未提供数据库会话，使用传统方式创建")
            from models import SessionLocal
            self._use_local_session = True
        else:
            self._use_local_session = False

    def _get_db_session(self):
        """获取数据库会话"""
        if self.db is not None:
            return self.db
        else:
            # 向后兼容：创建临时会话
            from models import SessionLocal
            return SessionLocal()

    def _close_db_session(self, db_session):
        """关闭数据库会话（仅在使用临时会话时）"""
        if self._use_local_session:
            db_session.close()

    def init_requestor(self):
        """
        初始化请求者信息，获取用户ID
        """
        try:
            # 提取消息内容
            if self.wxmsg.msgtype == 'text' and self.wxmsg.text:
                self.query = self.wxmsg.text.content
            
            # 检查用户是否存在并设置用户信息
            self.check_user_exists()
            
            logger.info(f"[聊天处理器] 👤 用户信息已设置: {self.nickname} (ID: {self.user_id}, 角色: {self.role})")
                
        except Exception as e:
            logger.error(f"[聊天处理器] ❌ 初始化请求者失败: {e} - {traceback.format_exc()}")
            # 出错时设置为匿名用户
            self.user = None
            self.user_id = 1
            self.name = None
            self.nickname = self.wxmsg.from_.userid
            self.role = "ANONYMOUS"

    def check_user_exists(self, name=None):
        """
        检测用户是否存在，主要检查nickname这是唯一标识符
        直接设置类属性，不返回值
        :param name: 暂时没用的
        """
        logger.debug("[DB] 🔍 检查用户是否存在")
        
        # 获取数据库会话
        db = self._get_db_session()
        try:
            # 使用from_.userid作为nickname进行查询
            query = db.query(Users).filter(
                Users.nickname == self.wxmsg.from_.userid,
                Users.is_deleted == False
            )
            
            if name:
                query = query.filter(Users.name == name)
                
            user = query.first()
            
            if user:
                logger.debug(f"[DB] ✅ 用户存在: {user.nickname}")
                # 直接设置类属性
                self.user = user
                self.user_id = user.id
                self.name = user.name
                self.nickname = user.nickname
                self.role = user.role
            else:
                logger.debug(f"[DB] ❌ 用户不存在: {self.wxmsg.from_.userid}")
                # 设置为匿名用户
                self.user = None
                self.user_id = 1
                self.name = None
                self.nickname = self.wxmsg.from_.userid
                self.role = "ANONYMOUS"
                
        except Exception as e:
            logger.error(f"[DB] ❌ 查询用户失败: {e} - {traceback.format_exc()}")
            # 出错时设置为匿名用户
            self.user = None
            self.user_id = 1
            self.name = None
            self.nickname = self.wxmsg.from_.userid
            self.role = "ANONYMOUS"
        finally:
            self._close_db_session(db)

    async def build_chat(self):
        """
        把解析步骤放入chat数据库，如果用户没有注册过，则用anonym替代
        :return:
        """
        self.init_requestor()  # regenerate user info
        
        # 创建时间戳 - 使用当前时间，因为WXWorkIn结构中没有create_time字段
        current_time = datetime.datetime.now()
        
        # 获取数据库会话
        db = self._get_db_session()
        try:
            chat = Chat(
                user_id=self.user_id,
                query=self.query,
                query_time=current_time,
                actions=str(self.actions),
                answer=self.answer,
                ai_answer=self.ai_answer,
                raw_msg=json.dumps(self.wxmsg.model_dump(), ensure_ascii=False, indent=4),
                note=self.note
            )
            db.add(chat)
            db.commit()
            logger.debug(f"[DB] 💾 聊天记录已保存 - user_id: {self.user_id}, query: {self.query[:50]}...")
            
        except Exception as e:
            logger.error(f"[DB] ❌ 保存聊天记录失败: {e} - {traceback.format_exc()}")
            db.rollback()
        finally:
            self._close_db_session(db)

    def set_answer(self, answer: str, ai_answer: str = None):
        """
        设置回答内容
        
        Args:
            answer: 非AI回答
            ai_answer: AI回答
        """
        self.answer = answer
        if ai_answer:
            self.ai_answer = ai_answer

    def set_ai_answer(self, ai_answer: str):
        """
        设置AI回答内容
        
        Args:
            ai_answer: AI原始回答
        """
        self.ai_answer = ai_answer

    def add_action(self, action: str):
        """
        添加执行的动作
        
        Args:
            action: 动作描述
        """
        self.actions.append(action)

    def set_note(self, note: str):
        """
        设置备注信息
        
        Args:
            note: 备注内容
        """
        self.note = note

    def is_group_chat(self) -> bool:
        """
        判断是否为群聊
        
        Returns:
            True if 群聊, False if 私聊
        """
        return self.wxmsg.chattype == 'group'

    def get_user_id(self) -> str:
        """
        获取企业微信用户ID，对应表格中的nickname
        
        Returns:
            用户ID字符串
        """
        return self.wxmsg.from_.userid

    def get_message_content(self) -> str:
        """
        获取消息内容
        
        Returns:
            消息文本内容
        """
        if self.wxmsg.msgtype == 'text' and self.wxmsg.text:
            return self.wxmsg.text.content
        return ""

    def get_user_info_for_prompt(self, user=None) -> tuple[str, str]:
        """
        获取用于提示词的用户信息
        
        Args:
            user: 用户对象（可选，如果不提供则使用默认值）
            
        Returns:
            tuple: (nickname, role)
        """
        if user and user.id != 1:  # 如果有用户且不是匿名用户
            return user.nickname, user.role
        else:
            # 如果没有用户信息或者是匿名用户，使用微信的userid作为nickname
            nickname = self.wxmsg.from_.userid
            role = user.role if user else "ANONYMOUS"
            return nickname, role

    def get_chat_environment_info(self) -> str:
        """
        获取聊天环境信息
        
        Returns:
            str: "群聊" 或 "私聊"
        """
        return "群聊" if self.is_group_chat() else "私聊"

    def format_history_for_prompt(self, chat_history: list) -> str:
        """
        将聊天历史格式化为提示词可用的文本
        
        Args:
            chat_history: 聊天历史记录列表
            
        Returns:
            str: 格式化后的历史记录文本
        """
        if not chat_history:
            return "无历史记录"
        
        formatted_history = []
        for chat in chat_history:
            formatted_history.append(f"用户: {chat.query}")
            formatted_history.append(f"机器人: {chat.ai_answer}")
        
        return "\n".join(formatted_history)

    def get_prompt_context(self, user=None, chat_history=None) -> dict:
        """
        获取提示词所需的完整上下文信息
        
        Args:
            user: 用户对象（可选）
            chat_history: 聊天历史记录（可选）
            
        Returns:
            dict: 包含所有提示词变量的字典
        """
        nickname, role = self.get_user_info_for_prompt(user)
        is_group = self.get_chat_environment_info()
        history_text = self.format_history_for_prompt(chat_history or [])
        message_content = self.get_message_content()
        
        return {
            "NICKNAME": nickname,
            "ROLE": role,
            "IS_GROUP": is_group,
            "history_text": history_text,
            "message_content": message_content
        }

